#include "copyfilestask.h"
#include "basetype.h"
#include "copyfile.h"
#include "utils.h"
#include <QDir>
#include <QFile>
#include <QFileInfo>
#include <QtDebug>

namespace yc {

CopyFilesTask::CopyFilesTask(const QList<QString>& file_names, const QString& target_dir, int id,
                             QObject* parent)
    : Task(id, true, 0, parent),
      file_names_(file_names),
      target_dir_(target_dir),
      copy_file_(nullptr),
      pos_(0)
{
}

CopyFilesTask::CopyFilesTask(const QString& source_dir, const QString& exclude_suffixes,
                             const QString& target_dir, int id, QObject* parent)
    : Task(id, true, 0, parent), target_dir_(target_dir), copy_file_(nullptr), pos_(0)
{
    baseutils::enumFiles(QDir(source_dir), file_names_, exclude_suffixes);
}

qint64 CopyFilesTask::evaluateTotalMSecs() const
{
    qint64 total_msecs = 0;
    qint64 size;
    for (const QString& s : file_names_) {
        size = QFileInfo(s).size();
        if (size >= BaseConstants::SMALL_FILE_SIZE) {
            total_msecs += CopyFileWorker::calcFileIDCost(size);
            total_msecs += CopyFileWorker::copyFileCost(size);
        }
    }
    return total_msecs;
}

void CopyFilesTask::startImpl()
{
    startNext();
}

void CopyFilesTask::onCopyFinished(const QString& file_name, const QString& new_file_name)
{
    if (new_file_name.isEmpty()) {
        qDebug() << "failed to copy file" << file_name;
        Q_EMIT failed(LOGIC_ERROR, tr("Failed to copy file."));
    } else {
        Q_EMIT copyFinished(file_name, new_file_name);
        if (pos_ < file_names_.size()) {
            startNext();
        } else {
            Q_EMIT finished();
        }
    }
}

void CopyFilesTask::startNext()
{
    QDir dir(target_dir_);
    while (pos_ < file_names_.size()) {
        QFileInfo fi(file_names_.at(pos_));
        if (fi.size() < BaseConstants::SMALL_FILE_SIZE) {
            // direct copy
            QString id = CopyFileWorker::calcFileID(file_names_.at(pos_), false);
            QString new_name = dir.absoluteFilePath(id + "." + fi.suffix());
            QFileInfo fi2(new_name);
            if (!fi2.exists() || fi2.size() != fi.size()) {
                QFile::copy(file_names_.at(pos_), new_name);
            }
            Q_EMIT copyFinished(file_names_.at(pos_), new_name);
            pos_++;
        } else {
            // async copy
            if (!copy_file_) {
                copy_file_ = new CopyFile(this);
                connect(copy_file_, &CopyFile::finished, this, &CopyFilesTask::onCopyFinished);
            }
            copy_file_->copy(file_names_.at(pos_), dir.absolutePath(), QString());
            pos_++;
            return;
        }
    }
    if (isRunning()) {
        Q_EMIT finished();
    }
}
} // namespace yc
